perm filename TCPRX.MAC[IP,SYS] blob sn#680230 filedate 1982-10-14 generic text, type T, neo UTF8
;CWL:<403-TCP>TCPRX.MAC.40303  4-May-82 13:56:59, Edit by CLYNN
; Refresh IP options on each retransmission; newer RX algorithm
;<403-TCP>TCPRX.MAC.40301 29-Jan-82 15:08:04, Edit by CLYNN
; Updated for TCP release 3
; Parameters moved to STG, TRACEP becomes INTTRC
;[BBNF]<401-TCP>TCPRX.MAC.56, 10-Jul-81 15:38:00, Ed: CLYNN
; Fix: No room in RXINI

	SEARCH	INPAR,TCPPAR,PROLOG
	TTITLE	TCPRX
	SUBTTL	TCP Retransmitter, William W. Plummer, 15FEB77
	SWAPCD


COMMENT	!
	The Retransmitter task is call from the top level of the TCP
	when a connection deadline has elapsed.  The single packet at
	the head of the restransmission queue is sent again and its
	retranmission interval adjusted.  Should the maximum
	persistence of some message be exceeded, the user is notified
	and the connection aborted.

* REXMIT ...  3 ...... Retransmitter
* SETRXP ...  7 ...... Set up Retransmission parameters in a PKT
* RXPARS ...  8 ...... Change retransmission parameters
* RXINI ....  9 ...... Initialize RX process block

Two retransmission strategies are available.  The old initial
interval with backoff and the "newer" dynamic method.

The "newer" method is the default;  it is specified by a "retransmission
parameters word" (OPEN, SEND) of zero.  It uses a smoothed round trip
time estimate based on the formula

	SRTT = SRTT(last) * alpha + RTT * (1-alpha)

and the packet retransmission interval is computed by

	RXI = SRTT * beta

where	SRTT	is TSMRT	(initial value is TCPRX0)
	alpha	is TCPRXS	(scaled by 2**-(TCPRXF))
	RTT	is TODCLK(ACK)-PTG
	beta	is TCPRXV	(scaled by 2**-(TCPRXF))
	RXI	is PRXI

The old method is specified if the "retransmission parameters word" has
ever been non-zero.  It computes the minimum and maximum round trip times
for all packets in a TCPBG0 msec interval and then sets the estimated
retransmission time (TRXI, initial value from RX param word, or TCPDXI if 0)
to one-half second above the average estimated round trip time.  With each
retransmission of a packet, the next retransmission interval is the current
value * numinator / denominator (each from the RX param word or TCPDXN,
TCPDXD).
	!

; REXMIT	Retransmit for a connection

;TCB/	(Extended) Locked connection block. (Dequeued from RX queue)
;
;	CALL REXMIT
;Ret+1:	Always

REXMIT::LOCAL <LINBLK,NXRXI>
	PUSH P,PKT
	PUSH P,TPKT

	XMOVEI T1,TCBRXQ(TCB)	; Pointer to the retranmit queue
	LOAD PKT,QNEXT,(T1)	; Set pointer to first thing on queue
	SETSEC PKT,INTSEC	; Make extended address
	SETO LINBLK,		; Assume not a TVT
	CAMN PKT,T1		; If that is the head of the queue,
	  JRST REXMIX		; we are done.

; TVT processing

	JE TTVT,(TCB),REXM1B	; Jump if not a TVT
	JUMPGE LINBLK,REXM1B	; Jump if already have line locked
	LOAD T2,TVTL,(TCB)	; Get the line number
	JUMPLE T2,REXM1B	; TVTL may be 0 if RXing a SYN
	CALL LCKTTY		; Lock and get ptr to dynamic block
	  JUMPLE T2,REXM1A	; Not init'd yet
	MOVEM T2,LINBLK
	JRST REXM1B
REXM1A:	CALL ULKTTY
REXM1B:

; Common processing

	LOAD T1,PIDO,(PKT)	; Internet data offset in words
	XMOVEI TPKT,PKTELI(PKT)	; Pointer to Internet portion
	ADD TPKT,T1		; Pointer to TCP portion
	SKIPN TCPON		; Force error if TCP is turned off
	  JRST REXMI2

; If this is the first retransmission of this packet, reinitialize
; the retransmission parameters (Initial interval and discard
; time).   Since this is done as each packet appears at Send.Left,
; timeouts are avoided in the case where the receiver is very slow.

	JN PRXD,(PKT),REXM11	; Pkt has been RX'd at least once
	LOAD T1,PSEQ,(TPKT)	; Packet sequence number
	LOAD T2,TSLFT,(TCB)	; Send Left
	LOAD T3,PESEQ,(PKT)	; End sequence of the Packet
	CALL CHKWND		; Is Left within this Pkt?
	JUMPE T1,REXMI3		; No.  Retransmit if needed.
	CALL SETRXP		; Initialize the RX parameters
REXM11:

; This packet contains TSLFT or has already been retransmitted
; Check for Retransmission timeout

	LOAD T1,PDCT,(PKT)	; Get discard time for this pkt
	JUMPE T1,REXMI3		; Jump if no discard time specified
	CAML T1,TODCLK		; Packet undeliverable?
	  JRST REXMI3		; Not yet.

; A pkt has not been ACKed within the (send) timeout specified
; by the user, or TCP has been shut off (TCPON is 0)

REXMI2:	MOVEI T1,ELP+↑D9	; "Retransmission timeout"
	CALL USRERR		; Tell the user
	MOVEI T1,ELP+↑D14	; "Connection reset"
	CALL ABTCON		; Abort the connection
	JRST REXMIX		; Return to caller

; See if it is time to retransmit this packet.

REXMI3:	LOAD NXRXI,PRXI,(PKT)	; Get the current retransmit interval
	JN PINTL,(PKT),REXMI6	; Cannot RX if last still unsent

	LOAD T1,PXT,(PKT)	; Time of last transmission
	ADD NXRXI,T1		; Plus interval is time to RX
	SUB NXRXI,TODCLK	; Time before next RX
	JUMPG NXRXI,REXMI6	; Not yet time, go reschedule

; Re-transmit the packet.  Refresh IP options that might have been changed

	CALL TCPIIO		; Hope user hasn't changed them

	MOVE NXRXI,TCPRXW	; Time to use if zero window (note that
	JE TSWND,(TCB),REXM36	; PRXI is unchanged but won't look til later)

	JE <TRXPN,TRXPD>,(TCB),REXM32 ; Use newer method

	LOAD T1,PRXI,(PKT)	; Get the current retransmit interval
	LOAD T2,TRXPN,(TCB)	; Numerator of backoff ratio
	LOAD T3,TRXPD,(TCB)	; Denominator
	IMULI T1,0(T2)
	IDIVI T1,0(T3)
	JRST REXM34

; Estimates based only on round trip time are essentially constant
; retransmissions, which looses if a large round trip time is usual.

REXM32:	JN PRXD,(PKT),REXM33	; Jump if multiple retransmissions

	LOAD T1,TSMRT,(TCB)	; Current round trip estimate
	IMUL T1,TCPRXV		; Increase by (scaled) variance
	ASH T1,@TCPRXF		; Remove scale factor
	JRST REXM34

; Until we have the estimate use a backoff factor of about 2.

REXM33:	LOAD T2,PTG,(PKT)	; Time packet generated
	MOVE T1,TODCLK		; Now
	SUB T1,T2		; Time packet has been unACKed
				; Essentially doubles RX interval
REXM34:
	CAMLE T1,TCPRXX		; Limit to maximum
	  MOVE T1,TCPRXX
	STOR T1,PRXI,(PKT)	; Store back in the packet header
	MOVEM T1,NXRXI		; Save for signal
REXM36:

; Before queueing the packet for an interface, set RXd flag

	SETONE PRXD,(PKT)	; Indicate that packet has been RXd

	MOVX T1,PT%XX8		; Code for "being retransmitted"
	TDNE T1,INTTRC		; Want trace?
	  CALL PRNPKT		; Yes, tell the packet printer

REPEAT 0,<
	SKIPN STATF		; Taking statistics right now?
	  JRST REXMI4		; No.
	MOVEI T1,RXDLAY		; Select a histogram
	CALL TSTAMP		; Process the timestamp
	XMOVEI T1,OPUSE		; Select a time accumulator
	XMOVEI T2,EMTPKT	; Function to call
	MOVE T3,LINBLK		; TVT block if any
	CALL TIMCAL		; Time the call
	JRST REXMI5		; Go handle the next packet
REXMI4:
> ; End of REPEAT 0
	MOVE T1,LINBLK		; TVT block if any
	CALL EMTPKT		; Send off the packet
REXMI5:
	AOS RXPKCT		; Count retransmitted packets

; Now reschedule Retransmitter to run again when this packet should
; again be retransmitted

REXMI6:	XMOVEI T1,RX		; What to signal
	MOVE T2,NXRXI		; The desired interval
	CALL SIGNAL		; Cause ourself to run later

REXMIX:	SKIPL T2,LINBLK		; Running for a TVT?
	  CALL ULKTTY		; Yes.  Unlock it
	POP P,TPKT
	POP P,PKT
	RESTORE
	RET

; SETRXP (PKT, TCB)	 Initialize retransmission parameters in a pkt

;PKT/	(Extended) Packet pointer
;(TPKT/	(Extended) pointer to TCP part of packet)
;TCB/	(Extended) Locked connection block
;
;	CALL SETRXP
;Ret+1:	Always


SETRXP::

; Set packet discard time
; How should Source-quench & send timeout interact?

	LOAD T1,TSTO,(TCB)	; Send time out set by user
	SKIPE T1		; Use 0 if none specified
	  ADD T1,TODCLK		; Else compute the deadline
	STOR T1,PDCT,(PKT)	; Set the discard time in the packet

; Set initial retransmission interval

	JE <TRXPN,TRXPD>,(TCB),SETRX4 ; Use newer method

	LOAD T1,TRXI,(TCB)	; Get estimated Retrans. Interval.
	SKIPG T1		; Guard against bad extimate of rnd trip
	  MOVE T1,TCPDXI	; Choose default interval in that case
	LOAD T2,TRXPI,(TCB)	; Get possible user setting
	IMULI T2,↑D1000		; Convert to milliseconds
	SKIPE T2		; Did user set retrans parameters?
	  MOVE T1,T2		; Yes.  Use that initial interval
	JRST SETRX6

SETRX4:	LOAD T1,TSMRT,(TCB)	; Get estimated round trip time
	IMUL T1,TCPRXV		; Increase by (scaled) variance
	ASH T1,@TCPRXF		; Remove scale factor
SETRX6:
	CAMLE T1,TCPRXX		; Keep within bounds
	  MOVE T1,TCPRXX
	CAMGE T1,TCPRXN		; both ends.
	  MOVE T1,TCPRXN

	SKIPE INTTRC		; Actively tracing packets?
	  IMULI T1,↑D1 ;8	; Slow down retransmissions

	STOR T1,PRXI,(PKT)	; Set packet retrans interval
	RET

; RXPARS(TCB)		Change retransmission parameters

; Called by SEND and OPEN which allow the caller to change the
; retransmission characteristics -- Backoff rate and initial
; retransmission interval.

;TCB/	(Extended) Locked Connection Block
;T1/	Retrans. parameter word.  Format is that of TRXP.
;
;	CALL RXPARS
;Ret+1:	Always.

;Note:  Newly created TCBs have 0 in the TRXP word which
;means that the user has not chosen to override the use of
;measured round trip time as the way of selecting the retrans
;interval.  If the user sets TRXP, those parameters are used.

RXPARS::JUMPE T1,RXPARX		; No change wanted
	LOAD T2,TRXP,(TCB)	; Current settings
	CAMN T1,T2		; Different?
	  JRST RXPARX		; No.

;	NOSKED
	STOR T1,TRXP,(TCB)	; Put them in place for LOADs
	LOAD T2,TRXPN,(TCB)	; Get numerator
	LOAD T3,TRXPD,(TCB)	; and denominator of backoff fraction
	LOAD T4,TRXPI,(TCB)	; Initial interval in seconds
;	OKSKED

	SKIPN T2		; Get defaults
	  MOVE T2,TCPDXN
	SKIPN T3
	  MOVE T3,TCPDXD
	SKIPN T4
	  MOVE T4,TCPDXI
	CAMLE T3,T2		; Prevent interval from decreasing
	  MOVE T3,T2

	STOR T2,TRXPN,(TCB)	; Set it all into the TCB
	STOR T3,TRXPD,(TCB)
	STOR T4,TRXPI,(TCB)
RXPARX:	RET

; RXINI			Initialize RX process block

;	CALL RXINI
;Ret+1:	ALways, T1 zero if error

RXINI::	LOCAL <PRC>

	XMOVEI PRC,RX		; Pointer to the Process block for RX
	MOVX T1,QSZ		; Size of a queue head
	CALL GETBLK		; Head must be in same section as items
	JUMPE T1,RXINIX		; No room
	MOVEM T1,PRCQ(PRC)	; Input queue
	CALL INITQ		; Initialize it

	XMOVEI T1,PRCLCK(PRC)	; Lock
	CALL CLRLCK		; Initilize it

	XMOVEI T1,REXMIT	; Retransmitter function
	MOVEM T1,PRCROU(PRC)	; Routine address
	SETOM PRCWAK(PRC)	; No run time yet
	MOVE T1,[<GIW TCBQRX,TCB>]; Offset of RX queue in TCB
	MOVEM T1,PRCQOF(PRC)	; Store process block
	MOVE T1,[<GIW TCBTRX,TCB>]; Offset of RX run time in TCB
	MOVEM T1,PRCWOF(PRC)	; Store in process block
	HRLOI T1,377777		; Infinity
	MOVEM T1,PRCSGT(PRC)	; Set time of most recent signal
	XMOVEI T1,RXRNCT	; Pointer to run counter
	MOVEM T1,PRCRNC(PRC)	; Put in standard place
	XMOVEI T1,RXUSE		; Pointer to CPU use meter
	MOVEM T1,PRCTMR(PRC)	; Put in standard place
;	SETO T1,

RXINIX:	RESTORE
	RET

	TNXEND
	END